package com.eling.elcms.privilege.service.impl;

import com.eling.elcms.community.service.IOrgCustomizationService;
import com.eling.elcms.core.exception.BusinessException;
import com.eling.elcms.core.service.MailEngine;
import com.eling.elcms.core.webapp.controller.Msg;
import com.eling.elcms.core.webapp.util.RequestUtil;
import com.eling.elcms.privilege.model.User;
import com.eling.elcms.privilege.service.IUserFindPwdService;
import com.eling.elcms.privilege.service.IUserManager;
import com.eling.elcms.system.service.ICaptchaService;
import com.eling.elcms.system.service.IMobileValidateService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class UserFindPwdServiceImpl implements IUserFindPwdService {

	public static final String ACTIVE_TEMPLATE = "/api/user/validatefindpwdemail?pkUser={pkUser}&activetoken={activetoken}";

	@Autowired
	private IPasswordTokenManager passwordTokenManager;
	@Autowired
	private PasswordEncoder passwordEncoder;

	@Autowired
	private IMobileValidateService mobileValidateService;

	@Autowired
	private IUserManager userManager;
	
	@Autowired
	private ICaptchaService captchaService;
	
	@Autowired
	private IOrgCustomizationService orgCustomizationService;
	
	
	private static final Map<String, String> userRandomMap = new HashMap<>();

	MailEngine mailEngine = null;

	@Autowired
	public void setMailEngine(MailEngine mailEngine) {
		this.mailEngine = mailEngine;
	}

	/**
	 * 发送找回密码的邮件
	 * 
	 * @param request
	 * @param email
	 * @return
	 */
	@Override
	public Msg sendFindPwdEmail(HttpServletRequest request, String email) {
		String url = RequestUtil.getAppURL(request);
		User user = new User();
		user.setEmail(email);
		List<User> list = userManager.query(user);
		if (list.isEmpty()) {
			return new Msg("error");
		} else {
			User u = list.get(0);
			try {
				mailEngine.sendHtmlEmail(new String[] { "<" + email + ">" }, "support <support@e-ling.com.cn>", // 发件人
						"壹零后密码找回", // 主题
						null, // 图片
						"<html><head><meta http-equiv='Content-Type' content='text/html; charset=utf-8' /></head><body>"
								+ "<div >尊敬的用户" + email + "您好！</div>" + "<p>您在访问壹零后产品时点击了“忘记密码”链接，这是一封密码重置确认邮件。</p> "
								+ "<p>您可以通过点击以下链接重置帐户密码：</p> " + "<div style='width:600px'><a>" + url
								+ buildRecoveryPasswordUrl(u, ACTIVE_TEMPLATE) + "<a></div></p>"
								+ "<p>为保障您的帐号安全，请在24小时内点击该链接，您也可以将链接复制到浏览器地址栏访问。</p> "
								+ "<p>若如果您并未尝试修改密码，请忽略本邮件，由此给您带来的不便请谅解" + "<p>本邮件由壹零后系统自动发出，请勿直接回复！</body></html>", // e-mail内容,
						"logoimg");
			} catch (Exception e) {
				// TODO chenJF根据返回的error或者success，前台只判断是否是error或者success，如果都不是，那就提示邮件发送失败
			}
			return new Msg("success");
		}
	}

	public String generateRecoveryToken(final User user) {
		return passwordTokenManager.generateRecoveryToken(user);
	}

	private String buildRecoveryPasswordUrl(final User user, final String urlTemplate) {
		final String activetoken = generateRecoveryToken(user);
		final String pkUser = user.getPkUser() + "";
		return StringUtils.replaceEach(urlTemplate, new String[] { "{pkUser}", "{activetoken}" },
				new String[] { pkUser, activetoken });
	}

	/**
	 * 修改密码
	 * 
	 * @param request
	 * @param pkUser
	 * @param passWord
	 * @return
	 */
	@Override
	public Msg updateUserPwd(HttpServletRequest request, String pkUserKey, String passWord) {
		if(!userRandomMap.containsKey(pkUserKey)){
			return new Msg("keyNotExist");
		}
		String pkUserString = userRandomMap.get(pkUserKey);
		String[] pks = pkUserString.split("_");
		long genTime = Long.parseLong(pks[1]);
		long nowTime = System.currentTimeMillis();
		if((nowTime-genTime)/1000-600>0){
			return new Msg("keyTimeout");
		}
		long pkUser = Long.parseLong(pks[0]);
		User user = userManager.get(Long.valueOf(pkUser));
		user.setPassword(passwordEncoder.encode(passWord));
		userManager.save(user);
		userRandomMap.remove(pkUserKey);
		return new Msg("success");
	}

	/**
	 * 校验验证码
	 * 
	 * @param request
	 * @param username
	 * @param phone
	 * @param vcode
	 * @return
	 */
	@Override
	public Msg validateCode(HttpServletRequest request, String username, String phone, String vcode) {
		if (!mobileValidateService.validateCode(phone, vcode)) {
			return new Msg("overdueOrError");
		} else {
			// 验证成功后直接返回pkUser
			User user = new User();
			user.setCode(username);
			List<User> list = userManager.query(user);
			if (list.isEmpty()) {
				return new Msg("notRegister");
			} else if (StringUtils.isBlank(list.get(0).getPhone1()) || list.get(0).getPhone1().length() < 11) {
				return new Msg("notAssociatedMobilePhone");
			} else if (!phone.equals(list.get(0).getPhone1())) {
				return new Msg("notMatch");
			} else {
				long pkUser = userManager.query(user).get(0).getPkUser();
				String uid = UUID.randomUUID().toString();
				userRandomMap.put(uid, pkUser+"_"+System.currentTimeMillis());
				String result = pkUser+":"+uid;
				return new Msg(result);
			}
		}
	}

	/**
	 * 发送验证码
	 * 
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	@Override
	public Msg sendValidateCode(HttpServletRequest request, HttpServletResponse response) throws Exception {
		//发送验证码之前先校验验证码
		String captcha = request.getParameter("captcha");
		//TODO lijinsheng 先兼容老版本,等待所有版本图形验证码替换完成,在去掉
		if(!StringUtils.isEmpty(captcha)){
			String err = captchaService.validate(request.getSession().getId(), captcha, "findpwd");
			if (err != null) {
				throw new BusinessException(err);
			}	
		}
		
		String username = request.getParameter("username");
		String phone = request.getParameter("phone");
		String csid = request.getParameter("csid");
		String pkOrganization= request.getParameter("pkOrganization");
		
		User user = new User();
		List<User> list = new ArrayList<>();
		user.setCode(username);
		//如果机构主键被传进来说明未专署云否则为公有云
		if(StringUtils.isNotBlank(pkOrganization)){
			csid = orgCustomizationService.getCsidByPkOrg(Long.parseLong(pkOrganization))+"";
			if(!"2".equals(pkOrganization)){
				user.setUniqueRange(pkOrganization);
			}
		}
		list=userManager.query(user);
		//如果是公有云需要把专属云的用户移除（专属云和公有云的账号可能有相同的）
		if((!StringUtils.isNotBlank(pkOrganization))||"2".equals(pkOrganization)){
			list =list.stream().filter(a->a.getUniqueRange()==null).collect(Collectors.toList());
		}
		
		if (list.isEmpty()) {
			return new Msg("notRegister");
		} else if (StringUtils.isBlank(list.get(0).getPhone1()) || list.get(0).getPhone1().length() < 11) {
			return new Msg("notAssociatedMobilePhone");
		} else if (!phone.equals(list.get(0).getPhone1())) {
			return new Msg("notMatch");
		} else {
			String vcode = mobileValidateService.getValidateCode(phone);
			String message = "验证码：" + vcode + "; 您正在申请找回密码,请在2分钟内进行验证。";
			mobileValidateService.sendOnce(phone, message,StringUtils.isNotBlank(csid)?Integer.valueOf(csid):null);
			return new Msg("success");
		}
	}

	/**
	 * 校验邮件
	 */
	@Override
	public ModelAndView validateFindPwdEmail(String pkUser, String token, HttpServletRequest req,
			HttpServletResponse res) {
		User user = new User();
		user.setPkUser(Long.valueOf(pkUser));
		List<User> list = userManager.query(user);
		// 验证用户是否存在
		if (!list.isEmpty() && list.size() == 1) {
			User u = list.get(0);
			if (isRecoveryTokenValid(u, token)) {
				return new ModelAndView("redirect:/html/findpwd.html?pkUser=" + u.getPkUser() + "&message=success");
			} else {
				return new ModelAndView("redirect:/html/findpwd.html?pkUser=" + u.getPkUser() + "&message=overdue");
			}
		} else {
			return new ModelAndView("redirect:/html/findpwd.html?message=inexistence");
		}
	}

	private boolean isRecoveryTokenValid(final User user, final String cptoken) {
		return passwordTokenManager.isRecoveryTokenValid(user, cptoken);
	}
}
